<?php

namespace App\Models\lin;

use App\Exceptions\lin\UserException;
use App\Models\BaseModel;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use DB;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * App\Models\lin\LinUser
 *
 * @property int $id
 * @property string $username 用户名，唯一
 * @property string|null $nickname 用户昵称
 * @property string|null $avatar 头像url
 * @property string|null $email 邮箱
 * @property string $create_time
 * @property string $update_time
 * @property string|null $delete_time
 * @method static \Illuminate\Database\Eloquent\Builder|LinUser newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|LinUser newQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|LinUser query()
 * @method static \Illuminate\Database\Eloquent\Builder|LinUser whereAvatar($value)
 * @method static \Illuminate\Database\Eloquent\Builder|LinUser whereCreateTime($value)
 * @method static \Illuminate\Database\Eloquent\Builder|LinUser whereDeleteTime($value)
 * @method static \Illuminate\Database\Eloquent\Builder|LinUser whereEmail($value)
 * @method static \Illuminate\Database\Eloquent\Builder|LinUser whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|LinUser whereNickname($value)
 * @method static \Illuminate\Database\Eloquent\Builder|LinUser whereUpdateTime($value)
 * @method static \Illuminate\Database\Eloquent\Builder|LinUser whereUsername($value)
 * @mixin \Eloquent
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\lin\LinUserGroup[] $userGroup
 * @property-read int|null $user_group_count
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\lin\LinGroup[] $group
 * @property-read int|null $group_count
 * @property-read \App\Models\lin\LinUserIdentity|null $identity
 * @method static \Illuminate\Database\Query\Builder|LinUser onlyTrashed()
 * @method static \Illuminate\Database\Query\Builder|LinUser withTrashed()
 * @method static \Illuminate\Database\Query\Builder|LinUser withoutTrashed()
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\lin\LinGroup[] $groups
 * @property-read int|null $groups_count
 */
class LinUser extends BaseModel
{
    use SoftDeletes;

    protected $table = 'lin_user';

    protected $fillable = ['nickname', 'avatar', 'email', 'username'];

    public static function updateUserInfo($uid, $params)
    {
        $user = self::find($uid);
        if (empty($user)) throw new UserException();

        if (isset($params['nickname']) && !empty($params['nickname'])) {
            $data['nickname'] = $params['nickname'];
        }
        if (isset($params['avatar']) && !empty($params['avatar'])) {
            $data['avatar'] = $params['avatar'];
        }
        if (isset($params['email']) && !empty($params['email'])) {
            $data['email'] = $params['email'];
        }
        return $user->update($data);
    }

    public static function getUserByUID($uid)
    {
        try {
            $user = self::findOrFail($uid)->makeHidden('username');
        } catch (\Exception $e) {
            throw new UserException();
        }

        $user['admin'] = false;
        $auths = [];
        $groupIds = LinUserGroup::whereUserId($user->id)->pluck('group_id');
        if (in_array(1, $groupIds->toArray())) {
            $user['admin'] = true;
        } else {
            $permissionIds = LinGroupPermission::whereIn('group_id', $groupIds)->pluck('permission_id');
            $permissions = LinPermission::whereIn('id', $permissionIds)->where('mount', 1)->get(['module','name as permission'])->groupBy('module');
            foreach ($permissions as $key => $item){
                $auths[] = [
                    $key => $permissions[$key]
                ];
            }
        }
        $user['permissions'] = $auths;
        return $user;
    }

    public static function createUser($params)
    {
        $user = [
            'username' => $params['username'],
            'email' => $params['email'] ?? 0,
        ];
        DB::beginTransaction();//开启事务
        try {
            $uid = self::create($user)->id;
            if ($uid) {
                $identity = [
                    'user_id' => $uid,
                    'identifier' => $params['username'],
                    'credential' => md5($params['password'])
                ];
                LinUserIdentity::create($identity);
                $group = [];
                if (count($params['group_ids']) > 0) {
                    foreach ($params['group_ids'] as $group_id) {
                        $group[] = [
                            'user_id' => $uid,
                            'group_id' => $group_id,
                        ];
                    }
                    LinUserGroup::insert($group);
                }
            }
            DB::commit();//提交至数据库
        } catch (\Exception $e) {
            DB::rollback();//数据库回滚
            throw  new UserException([
                'status' => 400,
                'msg' => '注册用户失败：' . $e->getMessage(),
                'code' => 10030
            ]);
        }
    }

    public static function getAdminUsers($params)
    {
        $ids = [];
        $rr = null;
        if (!empty($params['group_id'])) {
            $uList = LinUserGroup::whereGroupId($params['group_id'])->get();
            foreach ($uList as $uid) {
                array_push($ids, $uid['user_id']);//用户ids
            }
            $userList = self::with('groups')->whereIn('id', $ids)->get();//选择组
        } else {
            $uList = LinUserGroup::whereGroupId(1)->get();
            foreach ($uList as $uid) {
                array_push($ids, $uid['user_id']);//root用户ids
            }
            $userList = self::with('groups')->whereNotIn('id', $ids)->get();
        }

        $totalNums = $userList->count();
        list($start, $count, $page) = paginate();
        $userList = $userList->skip($start)->take($count);//分页
        return [
            'total' => $totalNums,
            'items' => $userList,
            'page' => $page,
            'count' => ceil($totalNums / $count) == $page ? ($totalNums - $start) : 10,
//            'total_page' => ceil($totalNums / $count)
        ];
    }

    public static function deleteUser($uid)
    {
        $user = self::getUserByUID($uid);
        if ($user['admin']) throw new UserException(10079);
        $user->delete();
        return true;
    }

    public static function updateUser($params)
    {
        $user = self::getUserByUID($params['uid']);
        if ($user['admin'] && !in_array(1, $params['group_ids'])) {
            throw new UserException(10078);
        }
        if (in_array(1, $params['group_ids'])) {
            throw new UserException(10073);
        }
        $olg_group = LinUserGroup::whereUserId($params['uid'])->get();
        foreach ($olg_group as $group) {
            if (!in_array($group['group_id'], $params['group_ids'])) {
                $user->groups()->detach($group['group_id']);
            }
        }
        $user->groups()->syncWithoutDetaching($params['group_ids']);
    }

    public function getAvatarAttribute($value)
    {
        if (!empty($value)) {
            return $this->prefixImgUrl($value, ['from' => 'LOCAL']);
        }
        return $value;
    }

    /**
     * @return BelongsToMany
     */
    public function groups(): BelongsToMany
    {
        return $this->belongsToMany('App\Models\lin\LinGroup', 'lin_user_group', 'user_id', 'group_id');
    }

    /**
     * @return HasOne
     */
    public function identity(): HasOne
    {
        return $this->hasOne('App\Models\lin\LinUserIdentity', 'user_id', 'id');
    }

    protected static function boot()
    {
        parent::boot();
        //在删除用户的同时执行操作
        static::deleting(function ($user) {
            // 删除与用户关联的信息
            $user->identity()->delete();
            $user->groups()->detach();
        });
    }
}
